﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
//类相当于结构体的上位替代，它在兼容结构体的同时，还允许函数（方法）写到类中
//同时，可以通过以下关键字将类内元素分为三类

//public：公有成员，类内外均可直接访问
//protected：保护成员，仅类内和派生类可访问
//private：私有成员，仅类内可访问（默认权限）
//现阶段还没学到派生类，姑且将保护和私有当作一类，它们在各自的类外不能被使用，
//但可以调动类内公有的部分（如类内函数）来调用或使用，
//直到该关键字到下一个分类关键字或最后的大括号之前，全都是该关键字的作用区域


//定义类的关键字为class和struct，其行为稍有不同，当未显式使用上述分类关键字时，
//class会默认将成员设置为private（私有成员），而struct会默认将成员设置为public（公有成员）
//但为了增加代码可读性，建议显式使用访问权限关键字，而非依赖class与struct

//注：1.一般定义类时默认使用class关键字，如有需要，再改struct关键字
//    2.类进行的分类会产生不同的类域，也就是说，不同的类中可以有相同的命名
//    3.类中的函数默认使用了inline（即内联函数关键字）


////class类的简单示例
//class dzh1
//{
//	void Add(int x, int y = 1)//类中的主流写法是把方法（函数）放在变量前书写，
//							  //其中公有成员应放在最前面，保护在中间，私有在最后，
//							  //这里为了展示class类默认私有就稍稍打破了这个常规约定
//	{
//		std::cout << "该函数私有\n";
//	}
//public:
//	void fz(int x = 0, int y = 1)
//	{
//		_x = x;
//		_y = y;
//		std::cout << _x << " " << _y << std::endl;
//	}
//private:
//	int _x;//防止类中变量名与函数参数变量混淆，一般将类中变量名 前或后 加"_"
//	int _y = 10;//也是与结构体不同的一点，类中可以直接在初始化时给变量赋值
//};
//
//
//int main()
//{
//	dzh1 a;//类比结构体，定义结构体只是图纸，真要创建空间就需要定义变量，类也是如此，
//		   //同时，使用类创建的变量直接结合了结构体时的typedef，可以不写class dzh1 a了
//	
////	a.Add(1, 2);//可以看到，对于class，若为使用分类关键字，则会默认为私有类型，外部不能随意调用
//
////	a._x = 1;//调用a中的成员也是用"."，指针也是"->"，但由于_x和_y为私有类型，所以不可调用该函数
//	a.fz(1, 1);//1 1\n
//	dzh1* pa = &a;
//	pa->fz(3, 3);//3 3\n
//	return 0;
//}

//struct dzh2
//{
//	void Print(int x, int y = 999)
//	{
//		std::cout << x << " " << y << std::endl;
//	}
//private:
//	void swap(int& ra, int& rb)
//	{
//		int c = ra;
//		ra = rb;
//		rb = c;
//	}
//public:
//	int _x = 0;
//private://这里表明，在同一个类中，这三个权限关键字可以反复使用
//	    //但在C++类定义中，​​通常不建议频繁重复使用相同的访问控制关键字（如多次public或private）
//	    //当一个类中，既存在公有私有的函数，也存在公有私有的变量，
//	    //应该按照“将公有的函数和变量均放在最前面，其次时保护，私有”的顺序
//	int _y = 1;
//};
//
//int main()
//{
//	dzh2 b;
//	b.Print(1);//1 999\n
//	int x = 1, y = 2;
////	b.swap(x, y);//由于swap被设置为了private（私有），所以不能直接在类外部调用
//	int& rx = b._x;
//	rx = 38324;
//	std::cout << b._x << std::endl;//38324\n
//	return 0;
//}

//对象所占的空间的计算方式和结构体变量的内存计算方式（规则）完全一致
//但对于类中的成员函数，由于其在编译过程中，就被放到了代码区，所以不会占用类的内存
//特殊规则：当类中没有成员变量时，其所占内存大小不是0，而是1（为了方便计算）
class sz1
{
public:
	void Print()
	{
		std::cout << 1 << std::endl;
	}
	char _a;//偏移量为0开始，char类型使用一个字节，接下来偏移量为2
	int _x = 0;//对于int类型，要从偏移量为4的整数倍的地址开始存储，对于此时，即偏移量为4处，存储完毕后，偏移量为8
	char _b = 'b';//char类型，直接存储1字节，存储完毕，偏移量为9
	int _y;//同理，存储完毕后，偏移量为16，而对象与结构体变量一致，所占内存为其中成员的最大对齐数的整数倍
			//再此情况下，即为4的整数倍，即为16字节
};

class sz2//由于该类中没有成员变量，所以不占用字节，但根据C++标准，由空类创建的对象实际应占用1字节
{
public:
	void Print()
	{
		std::cout << 1 << std::endl;
	}
};

class sz3//与sz2同理，由该类创建的对象所占字节数也为1
{
public:
};

int main()
{
	std::cout << sizeof(sz1) << " " << sizeof(sz2) << " " << sizeof(sz3) << std::endl;//16 1 1\0
	return 0;
}